import {bCreate, created} from "@/lifecycle/types";
import {PropsWatcher} from "@/observe/index";
import {bUpdateT, handleLifecycle, updatedT} from "@/lifecycle";
import {$options, $data, $props, _watcher} from "@/instance";
import {isObject} from "@/utils";

const _create = {
  //  beforeCreate：此时实例的数据观测、计算属性和方法都未初始化
  [bCreate]() {

  },
  //  created：已经完成了数据观测、计算属性和方法的初始化。
  //  但是此时尚未生成真正的 DOM 节点，并且 `$el` 属性尚未挂载到实例上。
  [created](vm) {
    initData(vm);
    initMethods(vm);
    initWatch(vm);
    initComputed(vm);
    initProps(vm);
  },
}

export default _create;

export const initData = (vm) => {
  const {data} = vm[$options];
  let cloneData = data;
  if (typeof data === 'function') cloneData = data();
  const result = isObject(cloneData) ? cloneData : {};
  for (let dataKey in result) {
    vm[dataKey] = result[dataKey];
  }
  // console.log(result, 'data result')
  vm[$data] = result;
  new PropsWatcher(vm, ([newVal, oldVal], prop) => {
    console.log(`%c这是回调，属性 ${prop} 的值从 ${oldVal} 变为 ${newVal}，在这里批处理更新视图`, 'color: blue');
    handleLifecycle(vm, bUpdateT); // 视图更新前调这个生命周期，不是数据更新前
    handleLifecycle(vm, updatedT); // 视图更新后
  })
}

export const initMethods = (vm) => {
  const {methods} = vm[$options];
  if (isObject(methods)) {
    for (let methodKey in methods) {
      vm[methodKey] = methods[methodKey];
    }
  }
}

// TODO 还需要判断传入的每个key, 是对象还是函数，做不同的处理
export const initWatch = (vm) => {
  const {watch} = vm[$options];
  if (isObject(watch)) {
    vm[_watcher] = watch;
  }
  // Vue源码是类的实例，我这里是对象
}


export const initComputed = (vm) => {
  const {computed} = vm[$options];
  if (computed !== undefined && !isObject(computed)) {
    throw new Error('options.computed 应该是一个对象类型')
  }
  for (let key in computed) {
    const computedCb = computed[key];
    if (typeof computedCb !== 'function') throw new Error('The' + key + 'error: options.computed应该是一个函数类型')
    vm[key] = computedCb.bind(vm)();
  }
}


//  TODO 还需要判断是数组还是对象
// 如果是对象，拿到{type, default, required} 进行处理
// 实现props前，首先要实现:语法，或者v-bind语法
export const initProps = (vm) => {
  const {props} = vm[$options]; // 挂载
  if (props === undefined) return;
  // 数组
  if (props instanceof Array) {
    // const propsList = [];
    // for(let item in props){
    //   if(typeof item !== 'string') throw new Error('options.props为数组时的元素必须为string');
    //   vm[item] = item;
    // }
    vm[$props] = props;
    return;
  }

  // 对象
  if (isObject(props)) {
    for (let key in props) {
      vm[key] = props[key];
    }
    vm[$props] = props;
    return;
  }

  throw new Error('options.props 必须是一个数组或者对象')
  // console.log(propsMap, 'props result')
}
